package org.tools.att
{
	import flash.events.AsyncErrorEvent;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.StatusEvent;
	import flash.events.TimerEvent;
	import flash.text.StyleSheet;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.utils.Timer;
	
	import mx.containers.Canvas;
	import mx.controls.TextArea;
	import mx.core.UITextField;
	import mx.core.WindowedApplication;
	import mx.events.FlexEvent;	

	/**
	 * @author pettot
	 */
// DEF #####################################################
//
public	class	Receiver 	extends		Canvas
//public	class	Recever		extends 	Module
{
	private		const	FILL_UP_CHAR:String=' ';
//	private		var		log:String;
	private		var		ClassLength:uint;
	private		var		style:String='txt';
	private		var		fontSize:uint=14;
	private		var		_Counter:uint=0;
	private		var		isRawText:Boolean=false;
	private		var		sign:UITextField=new UITextField();
	private		var		clipBoardSign:UITextField=new UITextField();
	private		var		signChecker:Timer=new Timer(LocalTrace.SIGN<<3);
	private		var		scrollDownTimer:Timer=new Timer(LocalTrace.SIGN>>2,1);
	private		var		clipBoardSignRemover:Timer=new Timer(LocalTrace.SIGN<<2,1);
//	public		var		w:Number=0;
//	public		var		h:Number=0;
	public		var		clearEnable:Boolean=true;
	public		var		write2Top:Boolean=false;
	public		var		inverseStyle:Boolean=false;
	public		var		tArea:TextArea;
	public		var		bg:Canvas;
	
// DEF #####################################################
//
public	function	Receiver(){addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);}
public	function	onCreationComplete(e:FlexEvent):void
{
	setEvents(EventDispatcher(this));
	setStyleSheet();
	tArea.htmlText=''+
		'<br/><p class="l">   if you want to cut the traced text then press <b>Ctrl</b> + <b>X</b>   </p><br/>'+
		'<br/><p class="l">   if you want to copy the traced text to the clipboard press <b>Ctrl</b> + <b>C</b>   </p><br/>'+
		'<br/><p class="l">   if you want to change the client reload clear then press <b>Ctrl</b> + <b>A</b>   </p><br/>'+
		'<br/><p class="l">   if you want to change the color style then press <b>Ctrl</b> + <b>S</b>   </p><br/>'+
		'<br/><p class="l">   if you want to change the font size then press <b>Ctrl</b> + <b>+|-</b>   </p><br/>'+
		'';
	var format:TextFormat=new TextFormat();
		format.bold=true;
		format.align=TextFieldAutoSize.RIGHT;
		format.size=16;
		format.font='_typewriter';
	sign.name="sign";
	sign.multiline=true;
	sign.background=true;
	sign.mouseEnabled=false;
	sign.condenseWhite=false;
	sign.borderColor=0xFFFFFF;
	sign.backgroundColor=0xFF0000;
	sign.defaultTextFormat=format;
	sign.autoSize=TextFieldAutoSize.RIGHT;
	localMsg('(-)');
//	addChild(sign);

	clipBoardSign.name='clipBoardSign';
	clipBoardSign.textColor=0;
	clipBoardSign.multiline=false;
	clipBoardSign.background=true;
	clipBoardSign.backgroundColor=0x00FF00;
	clipBoardSign.defaultTextFormat=format;
	clipBoardSign.autoSize=TextFieldAutoSize.RIGHT;
	clipBoardSign.text='';
	clipBoardSignRemover.addEventListener(TimerEvent.TIMER,hideClipBoard);
	
	onResize();
	(new LocalTraceReceve()).client=this;
	signChecker.addEventListener(TimerEvent.TIMER,onLostContact);
	localMsg();
	trace('constructor');
	scrollDownTimer.addEventListener(TimerEvent.TIMER,scrollDown);	
}
//	raw ...	raw writeing text
public	function	raw(text:String):void
{
	isRawText=true;
	tArea.htmlText=(write2Top?'':tArea.htmlText)+'<p class="n">'+text+'</p>'+(write2Top?tArea.htmlText:'');
	isRawText=false;
}
//	use for normal
public	function	onTrace(className:String,...args):void		{style='n';addText(className,args);}
//	use for highlight
public	function	hTrace(className:String,...args):void		{style='h';addText(className,args);}
//	use for warnings (orange)
public	function	wTrace(className:String,...args):void		{style='w';addText(className,args);}
//	use for errors (red)
public	function	eTrace(className:String,...args):void		{style='e';addText(className,args);}
//	green	text
public	function	gTrace(className:String,...args):void		{style='g';addText(className,args);}
//	blue	text
public	function	bTrace(className:String,...args):void		{style='b';addText(className,args);}
//	yellow text
public	function	yTrace(className:String,...args):void		{style='y';addText(className,args);}
//	magenta text
public	function	mTrace(className:String,...args):void		{style='m';addText(className,args);}
//	cyan	text
public	function	cTrace(className:String,...args):void		{style='c';addText(className,args);}
//	silver	text (gray)
public	function	sTrace(className:String,...args):void		{style='s';addText(className,args);}
//	it is automaticaly called... if you call it clears the window
public	function	connected():void			{clear();signChecker.start();}
public	function	Sign():void
{
	signChecker.reset();
	signChecker.start();
//	sign.background=false;
	switch(sign.text)
	{
		case'(|)':	sign.text='(/)';	return;
		case'(/)':	sign.text='(-)';	return;
		case'(-)':	sign.text='(\\)';	return;
		default:	sign.text='(|)';	return;
	}
}
public	function	callback(id:String,content:*=undefined):void{this[id](content);}
public	function	clear():void	{_Counter=0;clearEnable?tArea.htmlText='':null;}
private	function	Counter(inc:Boolean=false):String	{return	inc?_Counter>999?''+(_Counter++)+'\t':''+(_Counter++)+'\t\t':_Counter>999?''+_Counter+'\t':''+_Counter+'\t\t';}
private	function	localMsg(...args):void
{
	String(sign.htmlText).length>3000?sign.text='':null;
	sign.htmlText='<p class="l">'+specialchars(String(args))+'</p>'+sign.htmlText;
//	sign.background=true;
//	onResize();
}
private	function	addText(className:String,args:Array):void
{
	tArea.htmlText=(write2Top?'':tArea.htmlText)+
		'<p class="'+(String(style).length?style:'txt')+'">'+
			Counter(true)+specialchars(prepare(className)+'|'+String(args))+
		'</p>'+
		(write2Top?tArea.htmlText:'');
	write2Top?null:scrollDownTimer.start();
	
//	sign.background?Sign():null;
	signChecker.reset();
	signChecker.start();
//	tArea.verticalScrollPosition=int.MAX_VALUE;
}
private	function	prepare(name:String):String
{
	if(!name.length){return fillUp(ClassLength);}
	name.length>ClassLength?ClassLength=name.length:null;
	name+=fillUp(ClassLength-name.length);
	return name;
}
private	function	fillUp(u:uint):String	{return	u>0?FILL_UP_CHAR+fillUp(--u):'';}
private	function	specialchars(s:String):String
{
	return	(s
		.replace(isRawText?' ':RegExp(/\n/g),	' ')
		.replace(RegExp(/\r/g),					'')
		.replace(RegExp(/</g),					'&lt;')
		.replace(RegExp(/\[class ([\w]+)\]/),	'$1')
		.replace(RegExp(/\[class ([\w]+)\]/g),	'[C $1]')
		.replace(RegExp(/\[object ([\w]+)\]/g),	'[$1]')
	);
}
private	function 	setEvents(s:EventDispatcher):void
{
	s.addEventListener(ErrorEvent.ERROR,					onError);
	s.addEventListener(StatusEvent.STATUS,					onStatus);
	s.addEventListener(IOErrorEvent.IO_ERROR,				onIOError);
	s.addEventListener(AsyncErrorEvent.ASYNC_ERROR,			onAsyncError);
	s.addEventListener(SecurityErrorEvent.SECURITY_ERROR,	onSecurityError);
	
	s.addEventListener(Event.RESIZE,			onResize);
	s.addEventListener(Event.SCROLL,			onScroll);

	s.addEventListener(KeyboardEvent.KEY_DOWN,	onKeybDown);
	s.addEventListener(KeyboardEvent.KEY_UP,	onKeybUp);

	s.addEventListener(MouseEvent.CLICK,		onClick);
}
private	function	allEvents(e:Event,txt:String=''):void{trace(txt);Sign();}
private	function	onLostContact(e:TimerEvent):void
{
	trace('onLostContact');
//	sign.background=true;
	signChecker.reset();
	(new LocalTraceReceve()).connect();
}
private	function	onResize(e:Event=null):void		
{
//	w=stage is Stage?stage.stageWidth:width;h=stage is Stage?stage.stageHeight:height;
//	sign.x=w-sign.width-100;sign.y=0;//h-sign.height-15;
//	clipBoardSign.x=w-clipBoardSign.width-100;clipBoardSign.y=0;
//	sign.x=w-sign.width-15;sign.y=h-sign.height-15;
//	clipBoardSign.x=w-clipBoardSign.width-15;clipBoardSign.y=0;
}
private	function	onScroll(e:Event):void				{allEvents(e);}
private	function	onKeybDown(e:KeyboardEvent):void{}
private	function	onKeybUp(e:KeyboardEvent):void
{
	allEvents(e,e.keyCode+"	key:"+e.keyLocation+','+e.charCode+"	ctrl:"+e.ctrlKey+"	shift:"+e.shiftKey+"	alt:"+e.altKey);
	if(!e.ctrlKey){return;}
	switch(e.charCode)
	{
		case	99: 	//	ctrl + C
//					if(tArea.selectionBeginIndex!=tArea.selectionEndIndex){return;}
//					clipBoardSign.text='the displayed data was copyed to the clip board';
//					System.setClipboard(tArea.text);
					break;
		case	120:	//	ctrl + X
//					String(tArea.text).length?System.setClipboard(tArea.text):null;
					clipBoardSign.text='the displayed data was moved to the clip board';
					var cE:Boolean=clearEnable;
					clearEnable=true;clear();clearEnable=cE;
					break;
		case	97: 	//	ctrl + A
					clearEnable=!clearEnable;
					clipBoardSign.text='the automatic clear is '+(clearEnable?"enabled":"disabled")+' now';
					break;
		case	45: 	//	ctrl + -		
					fontSize>3?fontSize--:null;
					fontSize--;
		case	43: 	//	ctrl + +
					fontSize++;
					setStyleSheet();
					clipBoardSign.text='the font size was changed to '+fontSize+' px';
					break;
		case	115:	//	ctrl + S
					inverseStyle=!inverseStyle;
					clipBoardSign.text='the style was changed now';
					setStyleSheet();
					break;
		case	100:	//	ctrl + D
					write2Top=!write2Top;
					clipBoardSign.text='the text direction was changed, now is '+(write2Top?'up side down':'normal');
					break;
		case	119:
					WindowedApplication(parentApplication).alwaysInFront=!WindowedApplication(parentApplication).alwaysInFront;
					
		default:	return;
	}
	clipBoardSignRemover.reset();
	clipBoardSignRemover.start();
//	addChild(clipBoardSign);
}
private	function	hideClipBoard(e:TimerEvent):void	{/*removeChild(clipBoardSign);*/}
private	function	onClick(e:MouseEvent):void
{
	allEvents(e,'local [x;y]:['+e.localX+';'+e.localY+']	Stage[x;y]:['+e.stageX+';'+e.stageY+']	d:'+e.delta);
//	sign.background?(new LocalTraceReceve()).connect():null;
}
private	function	onError(e:ErrorEvent):void{allEvents(e,e.text);}
private	function	onIOError(e:IOErrorEvent):void				{allEvents(e,e.text);}
private	function	onAsyncError(e:AsyncErrorEvent=null):void	{style='l';localMsg('	AsyncError	'+e.target+'	'+e.text);}
private	function	onSecurityError(e:SecurityErrorEvent):void	{style='l';localMsg('	SecurityError'+e.target+'	'+e.text);}
private	function	onStatus(e:StatusEvent):void				{style='l';localMsg('	Status		'+e.target+'	'+e.level);}

private	function	scrollDown(e:TimerEvent):void				
{
//	trace('before	'+	tArea.verticalScrollPosition);
	tArea.verticalScrollPosition=int.MAX_VALUE;
//	trace(' after	'+	tArea.verticalScrollPosition);
}
public	function	setStyleSheet():void
{
//	sign.textColor=inverseStyle?0xFFFFFF:0;
//	tf.backgroundColor=inverseStyle?0x000033:0xFFFFFF;

//	bg.backgroundColor=inverseStyle?0x000033:0xFFFFFF;
	var SS:StyleSheet=new StyleSheet();
	tArea.styleSheet=SS;
	SS.parseCSS(
	'p	{'+
		'font-family:	_typewriter;'+
		'font-size:		'+fontSize+';'+
		'letter-spacing:0;'+
		'text-align:	left;'+
		'text-decoration:none;'+
		'text-indent:	0;'+
	'}'+
	'.n	{'+	//	NOTICE		text
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
	'}'+
	'.h	{'+		//	HIGHLIGHTED	message
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
		'font-weight:	bold;'+
		'textDecoration:underline;'+
	'}'+
	'.w	{'+		//	WARNING	orange	message
		(inverseStyle?'color:	#FF9900;':'color:	#FF6600;')+
		'font-weight:	bold;'+
	'}'+
	'.e	{'+		//	ERROR	red		message
		(inverseStyle?'color:	#FF3333;':'color:	#CC0000;')+
		'font-weight:	bold;'+
	'}'+
	'.g	{'+		//	green		message
		(inverseStyle?'color:	#00FF00;':'color:	#00CC00;')+
		'font-weight:	bold;'+
	'}'+
	'.b	{'+		//	blue		message
		(inverseStyle?'color:	#9999FF;':'color:	#0000CC;')+
		'font-weight:	bold;'+
	'}'+
	'.y	{'+		//	yellow		message
		(inverseStyle?'color:	#FFFF00;':'color:	#CCCC00;')+
		'font-weight:	bold;'+
	'}'+
	'.m	{'+		//	magenta		message
		(inverseStyle?'color:	#FF00FF;':'color:	#CC00CC;')+
		'font-weight:	bold;'+
	'}'+
	'.c	{'+		//	cyan		message
		(inverseStyle?'color:	#00FFFF;':'color:	#009999;')+
		'font-weight:	bold;'+
	'}'+
	'.s	{'+		//	silver		message
		(inverseStyle?'color:	#999999;':'color:	#666666;')+
		'font-weight:	bold;'+
	'}'+
	'.l	{'+		//	LOCAL		message
		(inverseStyle?'color:	#FFFFFF;':'color:	#000000;')+
		'font-weight:	normal;'+
		'font-style:	italic;'+
	'}'+
	'');
	tArea.styleSheet=SS;
}
// END #####################################################
}	//class
}	//package
// END #####################################################